package com.mytime.resources;

import java.io.IOException;
import java.util.List;

import javax.jdo.PersistenceManager;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.restlet.data.CharacterSet;
import org.restlet.ext.json.JsonRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.ServerResource;

import com.mytime.database.Category;
import com.mytime.database.Event;
import com.mytime.database.PMF;
import com.mytime.database.Timetable;
import com.mytime.database.Venue;
import com.mytime.util.Functions;
import com.mytime.util.WSQuery;

public class AllVenues extends ServerResource {

	/**
     * Handles a GET HTTP request.
     * Returns all events from a given Venue. 
     * @param entity
     */
	@Get
	public Representation getVenues() throws Exception {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		JSONObject venuesObject = new JSONObject();
		JSONArray venues = new JSONArray();
		
		try {
			List<Venue> venuesList = WSQuery.getVenues(pm);
			
			for (Venue venue: venuesList) {
				venues.put(venue.toJSON());
			}
			
			venuesObject.put("venues", venues);
			
		} catch (Exception e) {
			e.printStackTrace();
			venuesObject.put("error", e.getMessage());			
			
		} finally {
			pm.close();
		}

		return getRepresentation(venuesObject);
	}

    /**
     * Handles a POST HTTP request.
     * Adds one or more venues. 
     * @param JSONObject containing the information of the venues to be added.
     * @return JSONObject with the result (success or error)
     */
	@Post
	public Representation acceptRepresentation(Representation entity) throws JSONException, IOException {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		JsonRepresentation rep = new JsonRepresentation(entity);
		JSONObject result = new JSONObject();
		
        try {
        	//Getting data
			JSONObject jsonobj = rep.getJsonObject();
			
			//Getting venues to be added
			JSONArray venues = jsonobj.getJSONArray("venues");
			int venuesAdded = 0;
			int venuesUpdated = 0;
			
			for (int i = 0; i < venues.length(); i++) {
				//Venue information
				JSONObject venueObj = venues.getJSONObject(i);
				
				//Getting name to create key
				String venueName = venueObj.getString("name");
				Venue venue = WSQuery.getVenue(venueName, pm);

				if (venue == null) {
					venue = new Venue(venueObj);
					venuesAdded += 1;
					
				} else {
					venuesUpdated += 1;
				}
				
				//Venue Events
				if (venueObj.has("events")) {
					JSONArray events = venueObj.getJSONArray("events");
					
					for (int k = 0; k < events.length(); k++) {
						JSONObject jsonEvent = events.getJSONObject(k);
						
						//Check if event already exists
						Event event = WSQuery.getEvent(jsonEvent.getString("name"), pm);
						if (event == null) {
							event = new Event(jsonEvent);
						} else {
							event.updateValues(jsonEvent);
						}
						
						//Save category
						if (jsonEvent.has("category")) {
							Category category = new Category();
							category.setName(jsonEvent.getString("category"));
							category.setId(Functions.removeSpecialCharacters(jsonEvent.getString("category")).
									toLowerCase().replaceAll(" ", "_"));

							event.setCategory(category.getId());							
							pm.makePersistent(category);
						}
						
						//Add venue to event List
						event.addVenue(venue.getKey());
						//Add event to Venue List
						venue.addEvent(event.getKey());
						
						//Add Event to system
						pm.makePersistent(event);
												
	    				//Get showtimes in this Venue
	    				if (jsonEvent.has("showtimes")	) {
	    					JSONArray showtimes = jsonEvent.getJSONArray("showtimes");
	    					
	    					for (int s = 0; s < showtimes.length(); s++) {
	    						JSONObject timeObj = showtimes.getJSONObject(s);
	    						
	    						Timetable entry = new Timetable();
	    						entry.setEventId(event.getEncodedKey());
	    						entry.setVenueId(venue.getEncodedKey());
	    						entry.setStartTime(timeObj.getString("startTime"));
	    						entry.setEndTime(timeObj.getString("endTime"));
	    						
	    						pm.makePersistent(entry);
	    					}
	    				}
					}
					
				}

				pm.makePersistent(venue);
        	}
			
			result.put("Added", venuesAdded);
			result.put("Updated", venuesUpdated);
			
        } catch (JSONException e) {
			e.printStackTrace();
			result.put("error", e.getMessage());
			
		} finally {
    		pm.close(); 		
    	}
        
        return getRepresentation(result);

	}
	
	/**
	 * Returns the JSON representation for a given JSON object.
	 * */
    private Representation getRepresentation(JSONObject jsonObject) {
    	JsonRepresentation jr = new JsonRepresentation(jsonObject);
    	jr.setCharacterSet(CharacterSet.UTF_8);
    	
    	return jr;
    }    

}
